package cn.wizzer.app.web.commons.doc;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.shiro.util.CollectionUtils;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class NewDocU {


    public static void main(String[] args)  {
        try{
            XWPFDocument document = new XWPFDocument();


            // 创建第一个节并设置页眉

            XWPFParagraph paragraph1 = document.createParagraph();

            XWPFRelation relation1 = XWPFRelation.HEADER;
            int relationIndex1 = 1;
            List<POIXMLDocumentPart.RelationPart> listRelationPart1 = document.getRelationParts();
            XWPFHeader header1 = null;
            for (POIXMLDocumentPart.RelationPart rp : listRelationPart1) {
                if (rp.getRelationship().getRelationshipType().equals(relation1.getRelation())) {
                    relationIndex1++;
                    header1 = rp.getDocumentPart();
                }
            }
            if(header1 == null){
                header1 = (XWPFHeader) document.createRelationship(relation1, XWPFFactory.getInstance(), relationIndex1);
            }
            //CTSectPr sectPr1 = document.getDocument().getBody().addNewSectPr();
            CTSectPr sectPr1 = document.createParagraph().getCTP().addNewPPr().addNewSectPr();
            sectPr1.addNewType().setVal(STSectionMark.Enum.forString("continuous"));
            //XWPFHeaderFooterPolicy headerFooterPolicy1 = new XWPFHeaderFooterPolicy(document, sectPr1);
            //XWPFHeader header1 = headerFooterPolicy1.createHeader(XWPFHeaderFooterPolicy.DEFAULT, new XWPFParagraph[]{});
            XWPFParagraph headerParagraph1 = header1.createParagraph();
            //headerParagraph1.getCTP().addNewPPr().addNewPStyle().setVal("Header");
            XWPFRun headerRun1 = headerParagraph1.createRun();
            headerRun1.setText("Header for the first section");
            String relationId = document.getRelationId(header1);
            sectPr1.addNewHeaderReference().setId(relationId);
            // 创建第一个段落
            XWPFRun run1 = paragraph1.createRun();
            run1.setText("First section content.");
            run1.addCarriageReturn();


            // 创建分节符
            XWPFParagraph separatorParagraph = document.createParagraph();
            //paragraph1.getCTP().addNewPPr().addNewSectPr();
            separatorParagraph.setPageBreak(true);


            //XWPFHeader header2 = (XWPFHeader) document.createRelationship(relation1, XWPFFactory.getInstance(), relationIndex1+1);
            CTSectPr sectPr2 = document.getDocument().getBody().addNewSectPr();
           // CTSectPr sectPr2 = document.createParagraph().getCTP().addNewPPr().addNewSectPr();
           // sectPr2.addNewType().setVal(STSectionMark.Enum.forString("continuous"));
            XWPFHeaderFooterPolicy headerFooterPolicy2 = new XWPFHeaderFooterPolicy(document, sectPr2);
            XWPFHeader header2 = headerFooterPolicy2.createHeader(XWPFHeaderFooterPolicy.DEFAULT, new XWPFParagraph[]{});
            XWPFParagraph headerParagraph2 = header2.createParagraph();
            //headerParagraph2.getCTP().addNewPPr().addNewPStyle().setVal("Header");
            XWPFRun headerRun2 = headerParagraph2.createRun();
            headerRun2.setText("Header for the second section");
            //String relationId1 = document.getRelationId(header2);
            //sectPr2.addNewHeaderReference().setId(relationId1);

            // 创建第二个段落
            XWPFParagraph paragraph2 = document.createParagraph();
            XWPFRun run2 = paragraph2.createRun();
            run2.setText("Second section content.");


            // 保存文档
            FileOutputStream out = new FileOutputStream("C:\\Users\\allen\\Desktop\\docs\\document_with_section_headers.docx");
            document.write(out);
            out.close();

            /*System.out.println("Section headers set successfully.");*/

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 测试方法
     * 业务代码 MergeModel的type只是为了让我区分类型,在处理的时候更方便
     *
     * @throws IOException
     */
    public static void testMergeWord() throws IOException {
        /*List<MergeModel> collect = new ArrayList<>();
        collect.add(new MergeModel("",  "L:\\文件1.docx"));
        collect.add(new MergeModel("zc","L:\\文件2.docx"));
        collect.add(new MergeModel("xj","L:\\文件3.docx"));
        collect.add(new MergeModel("lr","L:\\文件4.docx"));
        collect.add(new MergeModel("qy1","L\\文件5.docx"));
        collect.add(new MergeModel("fz","L:\\文件6.docx"));
        collect.add(new MergeModel("fz","L:\\文件7.docx"));
        collect.add(new MergeModel("fz","L:\\文件8.docx"));
        collect.add(new MergeModel("fz","L:\\文件9.docx"));
        collect.add(new MergeModel("fz","L:\\文件10.docx"));
        collect.add(new MergeModel("fz","L:\\文件11.docx"));
        collect.add(new MergeModel("fz","L:\\文件12.docx"));
        collect.add(new MergeModel("fz","L:\\文件13.docx"));
        collect.add(new MergeModel("fz","L:\\文件14.docx"));
        collect.add(new MergeModel("fz","L:\\文件15.docx"));
        collect.add(new MergeModel("fz","L:\\文件16.docx"));*/
        List<String> srcDocxs = new ArrayList<>();

    }

    /**
     * 合并docx文件
     *
     * @param srcDocxs 需要合并的目标docx文件
     * @param destDocx 合并后的docx输出文件
     */
    public static XWPFDocument mergeDoc(XWPFDocument src1Document, List<String> srcDocxs) throws IOException {
        int fzStartIndex = 0;
        int opcpSize = srcDocxs.size();
        //获取的OPCPackage对象大于0时，执行合并操作
        if (opcpSize > 0) {
            try {
                dealCover(src1Document);
                boolean firFz = false;
                //OPCPackage大于1的部分执行合并操作
                List<XWPFParagraph> headerParagraphs = new ArrayList<>();
                List<XWPFParagraph> fzFooterParagraphs = new ArrayList<>();
                for (int i = 0; i < opcpSize; i++) {
                    XWPFDocument src2Document = new XWPFDocument(POIXMLDocument.openPackage(srcDocxs.get(i)));

                    clearSectPr(src2Document);
                    //if (mergeModel2.isReportModuleWord()) {
                    BigInteger startNum = new BigInteger("1");
                    copySectPr(src2Document, startNum);
                    src2Document.createParagraph().createRun().addBreak(BreakType.PAGE);
                    //}

                    // if(mergeModel2.getType().startsWith("fz")){
                    // 只需要拿一次
                    if (CollectionUtils.isEmpty(headerParagraphs)) {
                        List<XWPFHeader> headerList = src2Document.getHeaderList();
                        for (XWPFHeader xwpfHeader : headerList) {
                            String text = xwpfHeader.getText();
                            if (StringUtils.isNotBlank(text.trim())) {
                                headerParagraphs = xwpfHeader.getParagraphs();
                                break;
                            }
                        }
                    }
                    // 只需要拿一次
                    if (CollectionUtils.isEmpty(fzFooterParagraphs)) {
                        List<XWPFFooter> footerList = src2Document.getFooterList();
                        for (XWPFFooter xwpfFooter : footerList) {
                            String text = xwpfFooter.getText();
                            if (StringUtils.isNotBlank(text.trim())) {
                                fzFooterParagraphs = xwpfFooter.getParagraphs();
                                break;
                            }
                        }
                    }
                    // }

                    List<IBodyElement> bodyElements = src2Document.getBodyElements();
                    for (IBodyElement element : bodyElements) {
                        if (element instanceof XWPFParagraph) {
                            XWPFParagraph paragraph = (XWPFParagraph) element;
                            XWPFParagraph xwpfParagraph = src1Document.createParagraph();
                            xwpfParagraph.getCTP().set(paragraph.getCTP().copy());
                            CTP ctp = xwpfParagraph.getCTP();
                            CTPPr pPr = ctp.getPPr();
                            if (pPr == null) {
                                continue;
                            }
                            CTSectPr sectPr = pPr.getSectPr();
                            if (sectPr == null) {
                                continue;
                            }

                            createDefaultHeader(src1Document, sectPr, headerParagraphs);

                            copyFooter(src1Document, sectPr, fzFooterParagraphs);

                            if (!firFz) {
                                CTPageNumber ctPageNumber = sectPr.addNewPgNumType();
                                ctPageNumber.setStart(new BigInteger("1"));
                            }
                        } else if (element instanceof XWPFTable) {
                            XWPFTable xwpfTable = (XWPFTable) element;
                            XWPFTable table = src1Document.createTable();
                            table.getCTTbl().set(xwpfTable.getCTTbl().copy());
                        }
                    }
                }
                //将合并的文档写入目标文件中
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
            }
        }
        return src1Document;

    }

    /**
     * 处理封面的页脚页宽等信息
     *
     * @param docx
     */
    public static void dealCover(XWPFDocument docx) {
        // 这里是复制原文档的页脚信息,我这只有一个,所以直接这么处理了
        List<XWPFParagraph> footerParagraph = new ArrayList<>();
        List<XWPFFooter> footerList = docx.getFooterList();
        for (XWPFFooter xwpfFooter : footerList) {
            // 找到需要的页脚
            if (StringUtils.isNotBlank(xwpfFooter.getText()) && xwpfFooter.getText().contains("页脚关键信息")) {
                footerParagraph = xwpfFooter.getParagraphs();
                break;
            }
        }
        // 换页,业务需求
        docx.createParagraph().createRun().addBreak(BreakType.PAGE);
        List<XWPFParagraph> paragraphs = docx.getParagraphs();
        CTPageMar pgMar = null;
        CTPageSz pgSz = null;
        // 段落 从后往前找,复制宽度和边距等
        for (int p = paragraphs.size() - 1; p >= 0; p--) {
            XWPFParagraph lastParagraph = paragraphs.get(p);
            if (lastParagraph.getCTP().getPPr() == null || lastParagraph.getCTP().getPPr().getSectPr() == null) {
                continue;
            }
            CTSectPr sectPr = lastParagraph.getCTP().getPPr().getSectPr();

            pgMar = sectPr.getPgMar();
            pgSz = sectPr.getPgSz();
            break;
        }
        XWPFParagraph lastParagraph = docx.createParagraph();
        CTPPr pPr = lastParagraph.getCTP().getPPr();
        if (pPr == null) {
            pPr = lastParagraph.getCTP().addNewPPr();
        }
        //pPr.addNewWidowControl();
        CTSectPr sectPr = pPr.getSectPr();
        if (sectPr == null) {
            sectPr = pPr.addNewSectPr();
        }
        if (pgMar != null) {
            sectPr.addNewPgMar().set(pgMar.copy());
        }
        if (pgSz != null) {
            sectPr.addNewPgSz().set(pgSz.copy());
        }

        // 清空首页所有的页眉页脚信息
        // 因为自己要重新设置页脚,所以我直接清空了页眉页脚属性.
        clearSectPr(docx);

        // 设置为起始页
        CTPageNumber ctPageNumber = sectPr.addNewPgNumType();
        ctPageNumber.setStart(new BigInteger("1"));
        // 复制首页的页脚
        copyFooter(docx, sectPr, footerParagraph);
    }

    /**
     * 清空Sectpr的页眉页脚标签属性
     *
     * @param xwpfDocument
     */
    public static void clearSectPr(XWPFDocument xwpfDocument) {
        List<XWPFParagraph> paragraphs = xwpfDocument.getParagraphs();
        /*for (XWPFParagraph paragraph : paragraphs) {
            CTP ctp = paragraph.getCTP();
            CTPPr pPr = ctp.getPPr();
            if (pPr == null) {
                continue;
            }
            CTSectPr sectPr = pPr.getSectPr();
            if (sectPr == null) {
                continue;
            }
            CTPageSz pgSz = sectPr.getPgSz();

            CTSectPr ctSectPr = CTSectPr.Factory.newInstance();

            CTPageSz ctPageSz = ctSectPr.addNewPgSz();
            ctPageSz.set(pgSz);
            //ctSectPr.addNewDocGrid().set(sectPr.getDocGrid().copy());
            //if(sectPr.getPgMar()!=null) {
                ctSectPr.addNewPgMar().set(sectPr.getPgMar());
            //}
            //ctSectPr.addNewCols().set(sectPr.getCols().copy());
            //ctSectPr.addNewPgNumType().set(src2SectPr.getPgNumType().copy());
            ctSectPr.setRsidR(sectPr.getRsidR());
            ctSectPr.setRsidRPr(sectPr.getRsidRPr());
            ctSectPr.setRsidSect(sectPr.getRsidSect());
            pPr.setSectPr(ctSectPr);
        }*/
        CTSectPr sectPr1 = xwpfDocument.getDocument().getBody().getSectPr();
        if (sectPr1 == null) {
            return;
        }
        CTPageSz pgSz = sectPr1.getPgSz();

        CTSectPr ctSectPr = CTSectPr.Factory.newInstance();

        CTPageSz ctPageSz = ctSectPr.addNewPgSz();
        ctPageSz.set(pgSz.copy());
        ctSectPr.addNewDocGrid().set(sectPr1.getDocGrid().copy());
        ctSectPr.addNewPgMar().set(sectPr1.getPgMar().copy());
        ctSectPr.addNewCols().set(sectPr1.getCols().copy());
        //ctSectPr.addNewPgNumType().set(src2SectPr.getPgNumType().copy());
        ctSectPr.setRsidR(sectPr1.getRsidR());
        ctSectPr.setRsidRPr(sectPr1.getRsidRPr());
        ctSectPr.setRsidSect(sectPr1.getRsidSect());
        xwpfDocument.getDocument().getBody().setSectPr(ctSectPr);
    }

    /**
     * 页眉页脚的主要处理
     **/
    public static void copyFooter(XWPFDocument docx, CTSectPr sectPr, List<XWPFParagraph> xwpfParagraphList) {
        XWPFRelation relation = XWPFRelation.FOOTER;
        int relationIndex = getRelationIndex(relation, docx);
        XWPFFooter footer = (XWPFFooter) docx.createRelationship(relation, XWPFFactory.getInstance(), relationIndex);
        for (XWPFParagraph xwpfParagraph : xwpfParagraphList) {
            CTP ctp = footer.createParagraph().getCTP();
            ctp.set(xwpfParagraph.getCTP().copy());
        }
        // 把上面创建的footer的关联id,设到需要的分页节上CTSectPr
        String relationId = docx.getRelationId(footer);
        CTHdrFtrRef ctHdrFtrRef = sectPr.addNewFooterReference();
        ctHdrFtrRef.setId(relationId);
    }

    /**
     * 获取关联 rId的最大值
     *
     * @param relation
     * @param doc
     * @return
     */
    public static int getRelationIndex(XWPFRelation relation, XWPFDocument doc) {
        int i = 1;
        for (POIXMLDocumentPart.RelationPart rp : doc.getRelationParts()) {
            if (rp.getRelationship().getRelationshipType().equals(relation.getRelation())) {
                i++;
            }
        }
        return i;
    }

    /**
     * 把最外层的sectPr标签的属性做了copy,去除了页眉页脚等标签,带有设置开始页码的处理
     *
     * @param xwpfDocument
     */
    public static void copySectPr(XWPFDocument xwpfDocument, BigInteger startNum) {

        if (!xwpfDocument.getDocument().getBody().isSetSectPr()) {
            return;
        }
        CTBody body = xwpfDocument.getDocument().getBody();
        CTSectPr src2SectPr = body.getSectPr();

        //src2SectPr.set

        CTPageSz pgSz = src2SectPr.getPgSz();
        XWPFParagraph xwpfParagraph = xwpfDocument.getLastParagraph();

        //CTP ctp = CTP.Factory.newInstance();
        //XWPFParagraph xwpfParagraph = new XWPFParagraph(ctp, xwpfDocument);
        CTPPr pPr = xwpfParagraph.getCTP().getPPr();
        if (pPr == null) {
            pPr = xwpfParagraph.getCTP().addNewPPr();
        }
        if (pPr.getSectPr() != null) {
            return;
        }
        CTSectPr ctSectPr = pPr.addNewSectPr();
        //ctSectPr.set(src2SectPr.copy());
        //ctSectPr.unsetFootnotePr();

        CTPageSz ctPageSz = ctSectPr.addNewPgSz();
        ctPageSz.set(pgSz.copy());
        ctSectPr.addNewDocGrid().set(src2SectPr.getDocGrid().copy());
        ctSectPr.addNewPgMar().set(src2SectPr.getPgMar().copy());
        ctSectPr.addNewCols().set(src2SectPr.getCols().copy());
        //ctSectPr.addNewPgNumType().set(src2SectPr.getPgNumType().copy());
        ctSectPr.setRsidR(src2SectPr.getRsidR());
        ctSectPr.setRsidRPr(src2SectPr.getRsidRPr());
        ctSectPr.setRsidSect(src2SectPr.getRsidSect());

        if (startNum != null) {
            CTPageNumber ctPageNumber = ctSectPr.addNewPgNumType();
            ctPageNumber.setStart(startNum);
        }

    }

    /**
     * 复制已有页眉
     *
     * @param docx
     * @param ctSectPr
     * @param paragraphList
     */
    public static XWPFDocument createDefaultHeader(XWPFDocument docx, CTSectPr ctSectPr, List<XWPFParagraph> paragraphList) {
        XWPFRelation relation = XWPFRelation.HEADER;
        int relationIndex = getRelationIndex(relation, docx);
        XWPFHeader header = (XWPFHeader) docx.createRelationship(relation, XWPFFactory.getInstance(), relationIndex);
        for (XWPFParagraph xwpfParagraph : paragraphList) {
            XWPFParagraph paragraph = header.createParagraph();
            paragraph.getCTP().set(xwpfParagraph.getCTP().copy());
        }

        String relationId = docx.getRelationId(header);
        if(ctSectPr != null) {
            CTHdrFtrRef ctHdrFtrRef = ctSectPr.addNewHeaderReference();
            ctHdrFtrRef.setId(relationId);
        }
        return docx;
    }

}
